package com.xb.cloud.common.redis;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xb.cloud.common.JsonUtils;

import com.xb.cloud.common.SerializeUtils;
import com.xb.cloud.common.ValiDataUtil;
import com.xb.cloud.common.redis.template.RedisClientTemplate;
import com.xb.cloud.common.spring.SpringBeanFactoryUtil;

public class CacheUtil {
	private static Logger logger = LoggerFactory.getLogger(CacheUtil.class);

	/** redis获得锁的失效时间 */
	private static final int LOCK_EXPIRE_SECONDS = 5 * 60;

	/** 项目应用名(key前缀) */
	private static final String projectPrefixKey = "xb_cloud";

	/** redis是否启用标志 */
	private static final String REDIS_START_FLAG = "venus_redis_start_flg";

	/** redis是否成功 */
	private static final String REDIS_SUCCESS = "success";

	private static RedisClientTemplate redisCache = null;

	/**
	 * fixed: 高危 - 通过一个实例方法更新静态属性
	 * 
	 * @param factory
	 */
	private synchronized static void initSpring() {
		try {
			redisCache = SpringBeanFactoryUtil.getRedisCache();
			logger.info("系统缓存初始化  缓存对象:{}", redisCache);
		} catch (Exception e) {
			logger.error("系统缓存初始化错误 :{}", e);
		}
	}

	public void init() {
		CacheUtil.initSpring();
	}

	public static boolean existsByte(String key) {
		if (redisCache != null && key != null) {
			return redisCache.exists(key.getBytes());
		}
		return false;
	}

	public static Object getByte(String key) {
		if (redisCache != null && key != null) {
			return SerializeUtils.deserialize(redisCache.get(key.getBytes()));
		}
		return null;
	}

	public static void setexByte(String key, int seconds, Serializable serialize) {
		if (redisCache != null & key != null) {
			redisCache.setex(key.getBytes(), seconds, SerializeUtils.serialize(serialize));
		}
	}

	public static void delByte(String key) {
		if (redisCache != null & key != null) {
			redisCache.del(key.getBytes());
		}
	}

	public static void set(String key, String jsonString) {
		if (redisCache != null) {
			redisCache.set(key, jsonString);
		}
	}

	public static String get(String key) {
		if (redisCache != null) {
			return redisCache.get(key);
		}
		return null;
	}

	public static String hget(String mapKey, String filed) {
		if (redisCache != null) {
			if (mapKey != null && filed != null) {
				return redisCache.hget(mapKey, filed);
			}
		}
		return null;
	}

	public static Object hgetBytes(String mapKey, String filed) {
		if (redisCache != null) {
			if (mapKey != null && filed != null) {
				return SerializeUtils.deserialize(redisCache.hget(mapKey.getBytes(), filed.getBytes()));
			}
		}
		return null;
	}

	/**
	 * 判断map 中指定的key是否存在
	 * 
	 * @param mapKey
	 * @param filed
	 * @return
	 */
	public static boolean hexistsBytes(String mapKey, String filed) {
		if (redisCache != null) {
			if (mapKey != null && filed != null) {
				return redisCache.hexists(mapKey.getBytes(), filed.getBytes());
			}
		}
		return false;
	}

	public static boolean hexists(String mapKey, String filed) {
		if (redisCache != null) {
			if (mapKey != null && filed != null) {
				return redisCache.hexists(mapKey, filed);
			}
		}
		return false;
	}

	public static void hset(String mapKey, String filed, Object serialize) {
		if (redisCache != null) {
			if (mapKey != null && filed != null) {
				redisCache.hset(mapKey, filed, JsonUtils.beanToJson(serialize));
			}
		}
	}

	public static void hsetBytes(String mapKey, String filed, Serializable serialize) {
		if (redisCache != null) {
			if (mapKey != null && filed != null) {
				redisCache.hset(mapKey.getBytes(), filed.getBytes(), SerializeUtils.serialize(serialize));
			}
		}
	}

	/**
	 * 如果map中指定的key存在则不操作,不存在就保存
	 */
	public static void hsetnx(String mapKey, String filed, Object serialize) {
		if (redisCache != null) {
			if (mapKey != null && filed != null) {
				redisCache.hsetnx(mapKey, filed, JsonUtils.beanToJson(serialize));
			}
		}
	}

	public static void hsetnxBytes(String mapKey, String filed, Serializable serialize) {
		if (redisCache != null) {
			if (mapKey != null && filed != null) {
				redisCache.hsetnx(mapKey.getBytes(), filed.getBytes(), SerializeUtils.serialize(serialize));
			}
		}
	}

	/**
	 * 删除map中指定的key
	 */
	public static void hdel(String mapKey, String filed) {
		if (redisCache != null) {
			if (mapKey != null && filed != null) {
				redisCache.hdel(mapKey, filed);
			}
		}
	}

	public static void hdelBytes(String mapKey, String filed) {
		if (redisCache != null) {
			if (mapKey != null && filed != null) {
				redisCache.hdel(mapKey.getBytes(), filed.getBytes());
			}
		}
	}

	/**
	 * 获取map的全部值
	 * 
	 * @param cacheKeyMapSession
	 * @return
	 */
	public static Map<String, String> hgetAll(String mapKey) {
		if (redisCache != null) {
			if (mapKey != null) {
				return redisCache.hgetAll(mapKey);
			}
		}
		return null;
	}

	public static Map<byte[], byte[]> hgetAllBytes(String mapKey) {
		if (redisCache != null) {
			if (mapKey != null) {
				return redisCache.hgetAll(mapKey.getBytes());
			}
		}
		return null;
	}

	/*
	 * private static final String shardkey="1"; public static void
	 * publish(String channel, String message) { if(redisCache!=null){
	 * if(channel!=null&&message!=null){ redisCache.publish(shardkey, channel,
	 * message); } } }
	 * 
	 * public static void subscribe(JedisPubSub jedisPubSub,String... channels)
	 * { if(redisCache!=null){
	 * if(channels!=null&&jedisPubSub!=null&&channels.length>0){
	 * redisCache.subscribe(shardkey, jedisPubSub, channels); } } }
	 */

	/**
	 * 从尾部压入一个元素
	 * 
	 * @param key
	 * @param json
	 */
	public static void rpush(String key, String json) {
		if (redisCache != null) {
			if (key != null && json != null) {
				redisCache.rpush(key, json);
			}
		}
	}

	/**
	 * 获取key这个List，从第几个元素到第几个元素 LRANGE key start
	 * 
	 * @param key
	 * @param start
	 * @param end
	 */
	public static List<String> lrange(String key, int start, int end) {
		List<String> list = null;
		if (redisCache != null) {
			if (key != null) {
				list = redisCache.lrange(key, start, end);
			}
		}
		return list;
	}

	/**
	 * 获取key对应list长度
	 * 
	 * @param key
	 * @return
	 */
	public static long llen(String key) {
		long listSize = 0l;
		if (redisCache != null) {
			if (key != null) {
				listSize = redisCache.llen(key);
			}
		}
		return listSize;
	}

	/**
	 * 从list 头部删除一个元素，并返回删除的元素
	 * 
	 * @param key
	 */
	public static String lpop(String key) {
		String json = null;
		if (redisCache != null) {
			if (key != null) {
				json = redisCache.lpop(key);
			}
		}
		return json;
	}

	/**
	 * 对一个列表进行修剪(trim)，就是说，让列表只保留指定区间内的元素，不在指定区间之内的元素都将被删除。 举个例子，执行命令LTRIM list
	 * 0 2，表示只保留列表list的前三个元素，其余元素全部删除。
	 * 下标(index)参数start和stop都以0为底，也就是说，以0表示列表的第一个元素，以1表示列表的第二个元素，以此类推。
	 * 你也可以使用负数下标，以-1表示列表的最后一个元素，-2表示列表的倒数第二个元素，以此类推。 当key不是列表类型时，返回一个错误。
	 * 
	 * @param key
	 * @param start
	 * @param end
	 */
	public static void ltrim(String key, int start, int end) {
		if (redisCache != null) {
			if (key != null) {
				redisCache.ltrim(key, start, end);
			}
		}
	}

	/**
	 * 将object添加到缓存，设置生命周期
	 * 
	 * @param key
	 * @param seconds
	 * @param serialize
	 */
	public static void setex(String key, int seconds, Object serialize) {
		if (redisCache != null) {
			redisCache.setex(key, seconds, JsonUtils.beanToJson(serialize));
		}
	}

	/**
	 * 将object添加到缓存，设置生命周期
	 * 
	 * @param key
	 * @param seconds
	 * @param serialize
	 */
	public static String getex(String key) {
		if (redisCache != null) {
			return redisCache.get(key);
		}
		return null;
	}

	/**
	 * 检测key是否存在
	 * 
	 * @param key
	 * @return
	 */
	public static boolean exists(String key) {
		if (redisCache != null) {
			return redisCache.exists(key);
		}
		return false;
	}

	public static long del(String key) {
		if (redisCache != null) {
			return redisCache.del(key);
		}
		return 0;
	}

	/**
	 * 将str添加到缓存，设置生命周期
	 * 
	 * @param key
	 * @param seconds
	 * @param str
	 */
	public static void setstr(String key, int seconds, String str) {
		if (redisCache != null) {
			redisCache.setex(key, seconds, str);
		}
	}

	private static String getCompleteKey(String key) {
		if (null != projectPrefixKey && !"".equals(projectPrefixKey)) {
			return projectPrefixKey + ":" + key.trim();
		}
		return key;
	}

	/**
	 * 取得有效时间内的锁
	 * 
	 * @param key
	 * @param expireSeconds
	 *            有效时间 单位 秒
	 * @return
	 */
	public static boolean lock(String key, int expireSeconds) {
		if (null == key || "".equals(key.trim())) {
			return false;
		}
		if (expireSeconds == 0) {
			expireSeconds = LOCK_EXPIRE_SECONDS;
		}
		key = getCompleteKey(key);
		try {
			// TODO
			Long i = redisCache.setnx(key, String.valueOf(System.currentTimeMillis()));
			if (i.intValue() == 1) {
				redisCache.expire(key, expireSeconds);
				return true;
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return false;
	}

	/**
	 * 获取锁,默认锁定五分钟
	 * 
	 * @param key
	 * @return
	 */
	public static boolean lock(String key) {
		return lock(key, LOCK_EXPIRE_SECONDS);
	}

	/**
	 * 释放锁
	 * 
	 * @param key
	 * @return
	 */
	public static boolean unLock(String key) {
		if (null == key || "".equals(key.trim())) {
			return false;
		}
		key = getCompleteKey(key);
		try {
			Long i = redisCache.del(key);
			if (i.intValue() == 1) {
				return true;
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return false;
	}

	/**
	 * 判断是否启动cache
	 */
	public static boolean isStart() {
		if (redisCache == null) {
			return false;
		}

		redisCache.set(REDIS_START_FLAG, REDIS_SUCCESS);

		String redisStartFlg = redisCache.get(REDIS_START_FLAG);

		if (!ValiDataUtil.isNvl(redisStartFlg)) {
			return true;
		} else {
			return false;
		}
	}

	public static void hmset(String mapKey, Map<String, String> map) {
		if (redisCache != null) {
			if (mapKey != null) {
				redisCache.hmset(mapKey, map);
			}
		}
	}

}
